package com.narbeshuber.tablet.lasalara.http;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.ByteArrayBuffer;
import org.json.JSONArray;
import org.json.JSONObject;

import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.util.Log;

import com.narbeshuber.tablet.lasalara.LasaLaraActivity;
import com.narbeshuber.tablet.lasalara.fragment.BookFragment;
import com.narbeshuber.tablet.lasalara.model.Book;
import com.narbeshuber.tablet.lasalara.model.Chapter;
import com.narbeshuber.tablet.lasalara.model.Question;

public class UpdateBookTask extends AsyncTask<String, Object, String> {

	LasaLaraActivity lasalaraActivity;
	ProgressDialog dialog;
	String bookKey;

	public UpdateBookTask(LasaLaraActivity lasalaraActivity) {
		this.lasalaraActivity = lasalaraActivity;
	}

	@Override
	protected void onPreExecute() {
		super.onPreExecute();
		dialog = ProgressDialog.show(lasalaraActivity, "",
				"Updating book. Please wait...", true);
	}

	@Override
	protected String doInBackground(String... arg0) {

		try {
			
			bookKey = arg0[0];

			// get server chapters
			
			HttpClient httpclient = new DefaultHttpClient();
			HttpPost httppost = new HttpPost(
					"http://1.narbeshuber.appspot.com/getmchapters");
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
			nameValuePairs.add(new BasicNameValuePair("bk", bookKey));

			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			HttpResponse response = httpclient.execute(httppost);
			InputStream is = response.getEntity().getContent();
			BufferedInputStream bis = new BufferedInputStream(is, 700);
			ByteArrayBuffer baf = new ByteArrayBuffer(20);
			int current = 0;
			
			while ((current = bis.read()) != -1) {
				baf.append((byte) current);
			}
			
			final String chaptersRetval = new String(baf.toByteArray());
			
			is.close();
			bis.close();
			baf.clear();
			
			// check for version changes
			
			lasalaraActivity.getDbHelper().beginTransaction();
			List<Chapter> dbChapters = lasalaraActivity.getDbHelper().getAllChaptersFromBook(bookKey);
			lasalaraActivity.getDbHelper().endTransaction();
			
			JSONArray jsonChapters = new JSONArray(chaptersRetval);
			
			List<String> editedChapterKeys = new ArrayList<String>();

			for (int i = 0; i < jsonChapters.length(); i++) {
				JSONObject jsonChapter = jsonChapters.getJSONObject(i);	
					
				Chapter chapter = new Chapter();
				chapter.setChapterKey(jsonChapter.getString("ck"));
				chapter.setBookKey(bookKey);
				chapter.setAuthorName(jsonChapter.getString("name"));
				chapter.setAuthorEmail(jsonChapter.getString("email"));
				chapter.setTitle(jsonChapter.getString("title"));
				chapter.setDr(jsonChapter.getString("dr"));
				chapter.setVersion(jsonChapter.getString("version"));
				chapter.setInstitution(jsonChapter.getString("institution"));
				chapter.setAllowProp(jsonChapter.getString("allowProp"));
				
				// if chapter not in DB - add, continue
				if (!lasalaraActivity.getDbHelper()
						.isChapterInDB(bookKey, chapter.getChapterKey())) {
					
					lasalaraActivity.getDbHelper().beginTransaction();
					lasalaraActivity.getDbHelper().insertChapter(chapter);
					lasalaraActivity.getDbHelper().endTransaction();
					continue;
				}
				
				// update chapter data if new version
				for (Chapter dbChapter : dbChapters) {
					if (dbChapter.getChapterKey().equalsIgnoreCase(chapter.getChapterKey())
							&& !dbChapter.getVersion().equalsIgnoreCase(chapter.getVersion())) {
						
						lasalaraActivity.getDbHelper().beginTransaction();
						lasalaraActivity.getDbHelper().updateChapter(chapter);
						lasalaraActivity.getDbHelper().endTransaction();
						
						// store updated chapter keys for question retrieval
						editedChapterKeys.add(chapter.getChapterKey());
					}
				}
			}
			
			// for every edited chapters
			for (String editedChapterKey : editedChapterKeys) {
			
				// get server questions
				httppost = new HttpPost(
						"http://1.narbeshuber.appspot.com/getquestions");
				
				nameValuePairs = new ArrayList<NameValuePair>(2);
				nameValuePairs.add(new BasicNameValuePair("ck", editedChapterKey));
				
				httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
				response = httpclient.execute(httppost);
				is = response.getEntity().getContent();
				bis = new BufferedInputStream(is, 700);
				baf = new ByteArrayBuffer(20);
				current = 0;
				
				while ((current = bis.read()) != -1) {
					baf.append((byte) current);
				}
				
				final String questionsRetval = new String(baf.toByteArray());
				
				is.close();
				bis.close();
				baf.clear();
				
				// check for content changes
				
				lasalaraActivity.getDbHelper().beginTransaction();
				LinkedList<Question> dbQuestions = lasalaraActivity.getDbHelper()
						.getAllQuestionsFromChapter(editedChapterKey);
				lasalaraActivity.getDbHelper().endTransaction();
				
				JSONObject jsonQuestions = new JSONObject(questionsRetval);
				JSONArray questionsArray = jsonQuestions.getJSONArray("questions");
				JSONArray answersArray = jsonQuestions.getJSONArray("answers");
				
				
				LinkedList<Question> serverQuestions = new LinkedList<Question>();
				
				// map JSON to Question
				for (int i = 0; i < questionsArray.length(); i++) {
					Question question = new Question();
					question.setChapterKey(editedChapterKey);
					question.setQuestion(questionsArray.getString(i));
					question.setAnswer(answersArray.getString(i));
					question.setShowDate(null);
					question.setTimesAnswered(0);
					serverQuestions.add(question);
				}
				
				List<Question> intactQuestions = new ArrayList<Question>();
				
				// find intact questions/answers
				for (Question dbQuestion : dbQuestions) {
					for (Question serverQuestion : serverQuestions) {
						
						// save progress on question
						if (dbQuestion.getQuestion().equalsIgnoreCase(serverQuestion.getQuestion())
								&& dbQuestion.getAnswer().equalsIgnoreCase(serverQuestion.getAnswer())) {
							
							intactQuestions.add(dbQuestion);
							
						}
					}
				}
				
				
				// insert questions from server, add progress where possible
				
				for (Question serverQuestion : serverQuestions) {
					
					boolean doWrite = true;
					
					for (Question intactQuestion : intactQuestions) {
						if (serverQuestion.getQuestion().equalsIgnoreCase(intactQuestion.getQuestion())) {
							doWrite = false;
							break;
						}
					}
					
					if (doWrite) {
						lasalaraActivity.getDbHelper().beginTransaction();
						lasalaraActivity.getDbHelper().insertQuestion(serverQuestion);
						lasalaraActivity.getDbHelper().endTransaction();
					}
					
				}
			}
			
		} catch (Exception e) {
			Log.e("Exception: ", e.getMessage());
		}
		return "";
	}

	protected void onPostExecute(String result) {
		dialog.dismiss();
		
		lasalaraActivity.getDbHelper().beginTransaction();
		List<Book> books = lasalaraActivity.getDbHelper().getAllBooks();
		lasalaraActivity.getDbHelper().endTransaction();
		
		BookFragment.getInstance().getListAdapter().setBooks(books);
		BookFragment.getInstance().getListAdapter().refreshList();
	}
}
